import meta from '@/data/jianying/draft_meta_info.json'
import content from '@/data/jianying/draft_content.json'
import {nanoid} from 'nanoid'
// @ts-ignore
import {saveAs} from "file-saver";
import JSZip from "jszip";
import {ImageUrlToBlob} from "~/utils/FileUtils";
import {Animations, BackgroundMusics, Transitions, VideoEffects} from "~/data/ai/workeditdata";
import type {TTSOptionalParams, TTSOptions, TTSParams} from "~/composables/VoiceHooks";

export class JiangYing {
    // private static localPathBase = useGlobalConfig.jiangying.localProjectPath
    private static path = ''
    private static meta = meta
    private static content = content
    private static projectName = "jiangying_project"

    private static init() {
        // this.meta = meta
        // this.content = content
        // 清空项目素材
        this.clearMaterial()
        const {localProjectPath}=useWorkEditStore()
        this.projectName = useWorkEditStore().projectName
        this.path = localProjectPath + this.projectName + "/"
    }

    /**
     * 导入素材前，清空项目素材
     */
    static clearMaterial() {
        this.meta.draft_materials[0].value = []
        this.content.materials.videos = []
        this.content.materials.audios = []
        this.content.tracks = []
        this.content.materials.material_animations = []
    }

    /**
     * 导入素材
     * @param fileName
     * @param metetype
     */
    static importMaterial(fileName: string, metetype: "photo" | "video" | "music" = "photo") {
        // const localPathBase = useGlobalConfig.jiangying.localProjectPath
        const photoMaterial = {
            // create_time: Date.now(),
            // duration: useGlobalConfig.jiangying.duration,
            extra_info: fileName,
            file_Path: this.path + fileName,
            id: nanoid(36),
            metetype: metetype
        }
        console.log("保存到素材的的文件信息", photoMaterial)
        // @ts-ignore
        this.meta.draft_materials[0]["value"].push(photoMaterial)

    }

    /**
     * 新建轨道 TrackType: text video audio effect
     */
    static newTrack(TrackType: "text" | "video" | "audio" | "effect" = "video") {
        const track = {"id": nanoid(36), "type": TrackType, "segments": []}
        // @ts-ignore
        this.content.tracks.push(track)
        return track
    }

    /**
     * 添加素材
     * "material_name": "3aR9BMoeEO.png","path": "D:/JiangYingProject/3aR9BMoeEO.png",
     */
    static addMaterial(Mtype: "videos" | "audios", uuid: string, options: {
        material_name: string,
        path: string,
        // start:number,
        // duration:number,//单位微秒25*1000000
    }) {
        // 先加入videos清单，并且命名一个UUID
        // const uuid = nanoid(36)
        let type = "video"
        if (Mtype === "audios") {
            type = "extract_music"
        }
        // @ts-ignore
        this.content.materials[Mtype].push({
            category_name: "local",
            extra_type_option: 0,
            has_audio: true,
            id: uuid,
            name: options.material_name,
            path: options.path,
            type: type
        })
        // 再使用同样的UUID加入轨道,轨道0，默认主轨道
        // content.tracks[0].segments.push({
        //     material_id: uuid,
        //     source_timerange: {
        //         duration: 5000000,
        //         start: 0
        //     },
        //     speed: 1.0,
        //     //空片段的参数
        //     target_timerange: {
        //         duration: options.duration,
        //         start: options.start+options.duration,
        //     }
        // })
        // content.tracks[0].segments[content.tracks[0].segments.length - 1]
    }

    /**
     *增加特效
     */
    static addEffect(uuid: string, options: {
        effect_id: string,
        effect_name: string,
        effect_resource_id: string,
    }) {
        // @ts-ignore
        this.content.materials.video_effects.push({
            apply_target_type: 2,
            effect_id: options.effect_id,
            id: uuid,
            name: options.effect_name,
            platform: "all",
            render_index: 0,
            resource_id: options.effect_resource_id,
            type: "video_effect",
            value: 1
        })

    }


    /**
     * 根据id查找轨道
     */
    static getTrackById(trackId: string) {
        // @ts-ignore
        return this.content.tracks.find(item => item.id === trackId) as any
    }

    /**
     * 删除轨道，根据id
     */
    static deleteTrack(trackId: string) {
        // @ts-ignore
        this.content.tracks = this.content.tracks.filter(item => item.id !== trackId)
    }

    /**
     * 更新轨道
     */
    static updateTrack(trackId: string, New_Track: any) {
        //删除原轨道，用新的数据替换
        this.deleteTrack(trackId)
        // @ts-ignore
        this.content.tracks.push(New_Track)
    }

    /**
     * 重新计算时长
     */
    private static _reCalculateDuration() {
        const _k = [] as number[]
        this.content.tracks.forEach(item => {
            // @ts-ignore
            item["segments"].forEach(item2 => {
                if (item2.target_timerange.duration === 0) {
                    _k.push(item2.target_timerange.start + item2.target_timerange.duration)
                    console.log("@progress:_k的值为", _k)
                }
            })
        })
        console.log("_k的值为", _k)
        // @ts-ignore
        this.content.duration = Math.max(..._k)
    }

    /**
     * 给轨道添加素材
     * @param trackId
     * @param track_uuid
     * @param options
     */
    static addMaterialToTrack(trackId: string, track_uuid: string, options?: {
        material_id: string,
        start?: number,
        duration?: number,
        speed?: number,
    }) {
        //根据id查找track
        const track = this.getTrackById(trackId)
        track["segments"].push(
            {
                id: track_uuid,
                material_id: options?.material_id,
                visible: true,
                volume: 1,
                source_timerange: {
                    duration: options?.duration || 5000000,
                    start: 0
                },
                target_timerange: {
                    duration: options?.duration || 5000000,
                    start: options?.start || 0
                },
                extra_material_refs: []
            }
        )
        this.updateTrack(trackId, track)
    }

    /**
     * 添加动画
     *动画最重要的参数为resource_id
     */
    static addAnimation(material_animation_uuid: string, options: {
        category_id?: string,
        category_name?: string,
        duration?: number,
        id?: string,
        name?: string,
        resource_id: string,
        type: "in" | "out"|"group",
    }) {
        const _a = {
            animations: [{
                category_id: options?.category_id || "",
                category_name: options?.category_name || "",
                duration: options?.duration || 1000000,
                id: options?.id || "",
                name: options?.name || "",
                resource_id: options?.resource_id || "",
                type: options?.type || "in",
            }],
            id: material_animation_uuid,
            type: "sticker_animation"
        }
        // @ts-ignore
        this.content.materials.material_animations.push(_a)
    }

    /**
     *
     * 将动画添加到轨道
     * trackId 轨道id,  track_uuid 轨道上的segments唯一id
     */
    static addAnimationToTrack(trackId: string, track_segment_id: string, animation_uuid: string) {
        // 获取对应的轨道
        const track = this.getTrackById(trackId)
        console.log("track", track,track_segment_id)
        //     获取对应的segment
        const segment_index = track["segments"].findIndex((item: any) => item.id === track_segment_id)
        // 添加动画
        track["segments"][segment_index]["extra_material_refs"].push(animation_uuid)
        //更新轨道
        this.updateTrack(trackId, track)
    }

    /**
     *添加转场
     */
    static addTransition(transition_uuid: string, options: {
        duration?: number,
        effect_id?: string,
        resource_id: string,
    }) {
        const _t = {
            duration: options.duration || 1000000,
            effect_id: options.effect_id || "",
            id: transition_uuid,
            resource_id: options.resource_id,
            type: "transition"
        }
        // @ts-ignore
        this.content.materials.transitions.push(_t)
    }

    /**
     * 将转场添加到轨道
     */
    static addTransitionToTrack(trackId: string, track_segment_id: string, transition_uuid: string) {
        // 获取对应的轨道
        const track = this.getTrackById(trackId)
        //     获取对应的segment
        const segment_index = track["segments"].findIndex((item: any) => item.id === track_segment_id)
        // 添加动画
        track["segments"][segment_index]["extra_material_refs"].push(transition_uuid)
        //更新轨道
        this.updateTrack(trackId, track)
    }


    /**
     * 生成剪映草稿文件
     * @param dataList
     */
    static async getContent(dataList: TweetData[]) {
        console.log('导出剪映文件执行', dataList)
        // 初始化

        this.init()

        let start = 0
        let duration = 3000000
        // 添加轨道
        const video_track = this.newTrack("video") //视频轨道
        const effect_track = this.newTrack("effect")    //特效轨道
        const audio_track = this.newTrack("audio")  //音频轨道
        const bg_audio_track = this.newTrack("audio")//背景音频轨道
        // 创建一个压缩文件
        const zip = new JSZip()
        // 创建项目目录
        const project = zip.folder(this.projectName)
        for (const item of dataList) {
            console.log("开始处理", item.id)
            // 根据音频时长设定图片和视频的时长
            if (item.audio[0]) {
                duration = (await this.getAudioDuration(item.audio[0])) * 1000000
            }
            console.log("开始处理，计算音频时长结束")
            const video_track_id = nanoid(36)   //轨道上唯一id,图片和视频通用
            // 图片或者视频素材的文件名
            let fileName = ''
            //将视频保存到素材
            if (useWorkEditStore().useVideo && item.video) {
                console.log("视频素材", item.video)
                //导入素材库
                fileName = nanoid(10) + '.mp4'
                this.importMaterial(fileName, 'video')
                //导入轨道
                const material_uuid = nanoid(36)  //轨道的上的material_id，与videos关联

                //添加素材,用一个material_id与videos关联
                this.addMaterial("videos", material_uuid, {
                    material_name: fileName,
                    path: this.path + fileName,
                })
                //添加到轨道
                this.addMaterialToTrack(video_track.id, video_track_id, {
                    material_id: material_uuid,
                    start: start,
                    duration: duration,
                    speed: (await this.getVideoDuration(item.video)) / duration
                })
                //将素材添加到压缩包
                const blob = await ImageUrlToBlob(item.video)
                project?.file(fileName, blob)
            } else {
                //将图片保存到素材
                console.log("使用图片合成视频");
                if (item.images.length > 0) {
                    // 导入素材
                    fileName = nanoid(10) + '.png'
                    console.log("fileName before", fileName)
                    this.importMaterial(fileName, 'photo')
                    const material_uuid = nanoid(36)  //轨道的上的material_id，与videos关联

                    //添加素材,用一个material_id与videos关联
                    this.addMaterial("videos", material_uuid, {
                        material_name: fileName,
                        path: this.path + fileName,
                    })
                    // 添加到轨道
                    this.addMaterialToTrack(video_track.id, video_track_id, {
                        material_id: material_uuid,
                        start: start,
                        duration: duration,
                        speed: 1
                    })
                    //将素材添加到压缩包
                    const blob = await ImageUrlToBlob(item.images[item.choose_image_index||0])
                    project?.file(fileName, blob)
                } else {
                    //弹出提示，图片不存在
                    useSnackbarStore().showWarningMessage('图片不存在，请先生成图片')
                    return
                }
            }

            // 添加音频
            const audio_file_name = nanoid(10) + '.wav'
            if (item.audio) {
                //导入音频
                this.importMaterial(audio_file_name, 'music')
                // 加入素材
                const audio_uuid = nanoid(36)
                const audio_track_id = nanoid(36)
                this.addMaterial("audios", audio_uuid, {
                    material_name: audio_file_name,
                    path: this.path + audio_file_name,
                })
                // 导入轨道
                this.addMaterialToTrack(audio_track.id, audio_track_id, {
                    material_id: audio_uuid,
                    start: start,
                    duration: duration,
                    speed: 1
                })
            }
            const {effects, animations, transitions} = useWorkEditStore()
            // 添加特效
            if (item.video_effect) {
                const effect_uuid = nanoid(36)  //轨道的上的material_id，与videos关联
                const effect_track_id = nanoid(36)   //轨道上唯一id
                const _e = effects.find(item2 => item2.resource_id === item.video_effect)
                this.addEffect(effect_uuid, {
                    effect_id: _e?.effect_id!,
                    effect_name: _e?.name!,
                    effect_resource_id: _e?.resource_id!,
                })
                // 特效添加到特效轨道上
                this.addMaterialToTrack(effect_track.id, effect_track_id, {
                    material_id: effect_uuid,
                    start: start,
                    duration: duration,
                    speed: 1
                })
            }
            // 添加动画
            if (item.animation) {
                const animation_uuid = nanoid(36)
                const _a = animations.find(item2 => item2.resource_id === item.animation)
                console.log('对应的动画', _a)
                this.addAnimation(animation_uuid, {
                    category_id: _a?.category_id!,
                    category_name: _a?.category_name!,
                    id: _a?.id!,
                    resource_id: _a?.resource_id!,
                    duration: _a?.duration!,
                    type: _a?.type!,
                })
                // 动画添加到轨道上
                this.addAnimationToTrack(video_track.id, video_track_id, animation_uuid)
            }
            //添加转场
            if (item.transition) {
                const transition_uuid = nanoid(36)
                const _t = transitions.find(item2 => item2.request_id === item.transition)
                if (_t) {
                    this.addTransition(transition_uuid, {
                        duration: _t?.duration!,
                        resource_id: _t?.resource_id!,
                    })
                    // 转场添加到轨道上
                    this.addTransitionToTrack(video_track.id, video_track_id, transition_uuid)
                }
            }

            //重新计算时长
            this._reCalculateDuration()
            // 添加动画
            // this.addAnimation(0, "12088589", {
            //     duration: duration
            // })
            // 更新时长
            start += duration
            console.log("fileName after", fileName)

            // saveAs(item.images[0], fileName)
            //下载音频
            if (item.audio) {
                const _a = await ImageUrlToBlob(item.audio[0])
                project?.file(audio_file_name, _a)
                // saveAs(item.audio[0], audio_file_name)
            }
        }
        //添加背景音乐
        const {backgroundMusic_id} = useWorkEditStore()   //背景音乐id
        const audio_name = BackgroundMusics.find(item2 => item2.id === backgroundMusic_id)?.name
        const audio_src = BackgroundMusics.find(item2 => item2.id === backgroundMusic_id)?.src
        const bg_audio_filename = `bgmusic_${audio_name}_${nanoid(10)}.mp3`

        //导入素材
        this.importMaterial(bg_audio_filename, 'music')
        // 加入素材
        const audio_uuid = nanoid(36)
        const bg_audio_track_id = nanoid(36)
        this.addMaterial("audios", audio_uuid, {
            material_name: bg_audio_filename,
            path: this.path + bg_audio_filename,
        })
        // 导入轨道
        this.addMaterialToTrack(bg_audio_track.id, bg_audio_track_id, {
            material_id: audio_uuid,
            start: 0,
            duration: start,
            speed: 1
        })
        //将素材添加到压缩包
        const blob = await ImageUrlToBlob(audio_src!)
        project?.file(bg_audio_filename, blob)
        // 下载压缩文件
        zip.generateAsync({type: "blob"}).then(function (content) {
            saveAs(content, `jiangying_project.zip`);
        });

        this.saveJsonAsFile(this.meta, 'draft_meta_info.json')
        this.saveJsonAsFile(this.content, 'draft_content.json')
    }

    /**
     * 保存项目
     *
     */
    static async saveProject() {
        //保存到数据库
        const {
            projectName,
            Resolution_id,
            cover_url,
            full_contents,
            useVideo,
            backgroundMusic_id,
            contents
        } = useWorkEditStore()
        return await Client_POST('/tweet/savePrject', {
            user_id: useAuthStore().user?._id,
            projects: [{
                projectName,
                Resolution_id,
                cover_url,
                full_contents,
                useVideo,
                backgroundMusic_id,
                contents
            }]
        })
    }

    /**
     * 从服务器获取用户的项目和配置数据
     */
    static async getData():Promise<any> {
        const {user} = useAuthStore()
        const data = await Client_GET(   `/tweet/${user?._id}`)
        console.log("获取到的项目", data)
        return data
    }

    /**
     * 获取项目
     */
    static async getProjects():Promise<TweetProject[]> {
        const {projects}=await this.getData()
        return projects || []
    }

    /**
     * 保存为JSON文件
     * @param json
     * @param filename
     */
    static saveJsonAsFile(json: Object, filename: string) {
        // 将JSON对象转换为字符串
        const jsonString = JSON.stringify(json);
        // 创建一个Blob实例，里面包含JSON字符串
        const blob = new Blob([jsonString], {type: 'application/json'});
        saveAs(blob, filename)
    }

    /**
     * 获取音频时长
     */
    static async getAudioDuration(url: string): Promise<number> {
        console.log("获取音频时长,音频的路径", url)
        const audio = new Audio(url);
        return new Promise((resolve, reject) => {
            audio.addEventListener('canplaythrough', function () {
                const _d = audio.duration;
                resolve(_d);
            });
        })
    }

    /**
     * 获取视频时长
     */
    static async getVideoDuration(url: string): Promise<number> {
        return new Promise((resolve, reject) => {
            const video = document.createElement('video');
            video.src = url;
            video.onloadedmetadata = function () {
                console.log("video.duration", video.duration)
                resolve(video.duration); // 视频时长（以秒为单位）
            };
        })
    }
}


export interface PhotoMaterial {
    create_time: number;
    duration: number;
    extra_info: string;
    file_Path: string;
    height?: number;
    id: string;
    import_time?: number;
    import_time_ms?: number;
    item_source?: number;
    md5?: string;
    metetype: string;
}

// 工作空间的数据接口
export interface TweetData {
    id?: number
    content?: string
    prompts?: string
    images: string[]
    choose_image_index?: number
    audio: string[]
    isTalk?: boolean //是否是对话
    role?: string  //人物名称
    scene_id?: number  //场景id
    video: string
    transition?: string
    video_effect?: string
    animation?: string
}

export interface Role {
    // id: number;
    title: string;   //角色名称
    src: string;   //参考图片路径
    description: string   //角色特征
    voicemodel_id: number  //声音模型
    voice:TTSParams  //TTS模型
}

export interface Scene {
    id: number;
    title: string;   //场景名称
    src: string;   //参考图片路径
    description: string   //场景特征
}

export interface Audio {
    url: string
    duration: number
}

export interface ComfyModel {
    category?: string,
    name?: string,
    ckpt_id: number,//大模型id
    cover?: string,
    types?: number[]
}

export interface JYAnimation {
    anim_adjust_params?: any;
    category_id?: string;
    category_name?: string;
    duration?: number;
    id?: string;
    material_type?: string;
    name?: string;
    panel?: string;
    path?: string;
    platform?: string;
    request_id?: string;
    resource_id: string;
    start?: number;
    type?: 'in' | 'out' | 'group';
    preview_url?: string;
}

export interface JYTransition {
    category_id?: string;
    category_name?: string;
    duration?: number;
    effect_id?: string;
    id?: string;
    is_overlap?: boolean;
    name?: string;
    path?: string;
    platform?: string;
    request_id?: string;
    resource_id: string;
    type?: string;
    preview_url?: string;
}

export interface Effect_Adjust_param {
    default_value: number;
    name: string;
    value: number;
}

export interface JYEffect {
    adjust_params?: Effect_Adjust_param[];
    algorithm_artifact_path?: string;
    apply_target_type?: number;
    apply_time_range?: any;
    category_id?: string;
    category_name?: string;
    common_keyframes?: any[];
    disable_effect_faces?: any[];
    effect_id?: string;
    formula_id?: string;
    id?: string;
    name?: string;
    path?: string;
    platform?: string;
    render_index?: number;
    request_id?: string;
    resource_id: string;
    source_platform?: number;
    time_range?: any;
    track_render_index?: number;
    type?: string;
    value?: number;
    version?: string;
    preview_url?: string;
}

export interface TweetProject {
    projectName: string;
    Resolution_id: number;
    cover_url: string;
    full_contents: string;
    useVideo: boolean;
    backgroundMusic_id: number;
    contents: TweetData[];
}
export interface VoiceModel extends TTSOptionalParams{
    id:number,
    name:string,
    emotions:string[]
    tts:TTSChannel
    //ChatTTS
}
export type TTSChannel = 'ChatTTS' | 'GPTVits';